package net.ufrog.common.utils;

import net.ufrog.common.CoreConfig;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;

/**
 * 数字工具
 *
 * @author ultrafrog
 * @version 1.0, 2013-06-09
 * @since 1.0
 */
public class Numbers {

    private static Integer scale					= 2;
    private static RoundingMode roundingMode 		= RoundingMode.DOWN;

    private static ThreadLocal<Map<String, NumberFormat>> current = new ThreadLocal<>();

    /** 构造函数 */
    private Numbers() {}

    /**
     * 读取格式器
     *
     * @param pattern 表达式
     * @return 数字格式化对象
     */
    public static NumberFormat getFormat(String pattern) {
        Map<String, NumberFormat> mNumberFormat = current.get();
        if (mNumberFormat == null || !mNumberFormat.containsKey(pattern)) {
            if (mNumberFormat == null) {
                mNumberFormat = new HashMap<>();
                current.set(mNumberFormat);
            }
            mNumberFormat.put(pattern, new DecimalFormat(pattern));
        }
        return mNumberFormat.get(pattern);
    }

    /**
     * 格式化数字
     *
     * @param pattern 表达式
     * @param number 待格式数字
     * @return 格式化后的数字字符串
     */
    public static String format(String pattern, Number number) {
        return getFormat(pattern).format(number.doubleValue());
    }

    /**
     * 解析数字字符串
     *
     * @param pattern 表达式
     * @param source 源字符串
     * @return 解析后数字
     * @throws ParseException 格式不正确时抛出
     */
    public static Number parse(String pattern, String source) throws ParseException {
        return getFormat(pattern).parse(source);
    }

    /**
     * 格式化金额
     *
     * @param number 待格式数字
     * @return 金额字符串
     */
    public static String currency(Number number) {
        BigDecimal currency = new BigDecimal(number.toString()).setScale(2, RoundingMode.DOWN);
        return format(CoreConfig.getPatternCurrency(), currency);
    }

    /**
     * 格式化百分比
     *
     * @param number 待格式数字
     * @return 百分比字符串
     */
    public static String percent(Number number) {
        BigDecimal percent = new BigDecimal(number.toString()).setScale(4, RoundingMode.DOWN);
        return format(CoreConfig.getPatternPercent(), percent);
    }

    /**
     * 加
     *
     * @param number 被加数
     * @param another 加数
     * @return 结果数字
     */
    public static BigDecimal add(Number number, Number another) {
        return decimal(number).add(decimal(another)).setScale(scale, roundingMode);
    }

    /**
     * 减
     *
     * @param number 被减数
     * @param another 减数
     * @return 结果数字
     */
    public static BigDecimal subtract(Number number, Number another) {
        return decimal(number).subtract(decimal(another)).setScale(scale, roundingMode);
    }

    /**
     * 乘
     *
     * @param number 被乘数
     * @param another 乘数
     * @return 结果数字
     */
    public static BigDecimal multiply(Number number, Number another) {
        return decimal(number).multiply(decimal(another)).setScale(scale, roundingMode);
    }

    /**
     * 除
     *
     * @param number 被除数
     * @param another 除数
     * @return 结果数字
     */
    public static BigDecimal divide(Number number, Number another) {
        return decimal(number).divide(decimal(another), scale, roundingMode);
    }

    /**
     * 转换数字
     *
     * @param num 数字字符串
     * @return 数字
     */
    public static BigDecimal decimal(String num) {
        return new BigDecimal(num);
    }

    /**
     * 转换数字
     *
     * @param num 数字
     * @return 数字
     */
    public static BigDecimal decimal(Number num) {
        return decimal(num.toString());
    }
}
